<?php


namespace app\api\wxpay;

class Certificate
{
	public $WechatPaySdk;
	public function __construct($config)
	{
		$this->WechatPaySdk = new WechatPaySdk($config);
	}
	public function get_certificate()
	{
		try {
			$url = "https://api.mch.weixin.qq.com/v3/certificates";
			$header = $this->createAuthorization($url);
			$client = new \GuzzleHttp\Client(["headers" => $header]);
			$response = $client->get($url);
			$body = json_decode($response->getBody(), true);
			$data = [];
			foreach ($body["data"] as $certificate) {
				if (strtotime($certificate["expire_time"]) > time()) {
					$data = $certificate;
					continue;
				}
			}
			if ($data) {
				$certificate = $this->decryptToString($this->WechatPaySdk->apiv3key, $data["encrypt_certificate"]["associated_data"], $data["encrypt_certificate"]["nonce"], $data["encrypt_certificate"]["ciphertext"]);
				return ["code" => 1, "msg" => "获取成功", "data" => $certificate];
			} else {
				return ["code" => -1, "msg" => "没有可用证书"];
			}
		} catch (\Exception $e) {
			return ["code" => -1, "msg" => $e->getMessage()];
		}
	}
	public function decryptToString($aesKey, $associatedData, $nonceStr, $ciphertext)
	{
		if (strlen($aesKey) != 32) {
			throw new \Exception("无效的ApiV3Key，长度应为32个字节");
		}
		$ciphertext = \base64_decode($ciphertext, true);
		if (strlen($ciphertext) <= 16) {
			return false;
		}
		if (function_exists("\\sodium_crypto_aead_aes256gcm_is_available") && \sodium_crypto_aead_aes256gcm_is_available()) {
			return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $aesKey);
		}
		if (function_exists("\\Sodium\\crypto_aead_aes256gcm_is_available") && \Sodium\crypto_aead_aes256gcm_is_available()) {
			return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $aesKey);
		}
		if (PHP_VERSION_ID >= 70100 && in_array("aes-256-gcm", \openssl_get_cipher_methods())) {
			$ctext = substr($ciphertext, 0, -16);
			$authTag = substr($ciphertext, -16);
			return \openssl_decrypt($ctext, "aes-256-gcm", $aesKey, \OPENSSL_RAW_DATA, $nonceStr, $authTag, $associatedData);
		}
		throw new \Exception("AEAD_AES_256_GCM需要PHP 7.1以上或者安装libsodium-php");
	}
	public function createNoncestr($length = 32)
	{
		$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
		$str = "";
		for ($i = 0; $i < $length; $i++) {
			$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
		}
		return $str;
	}
	public function createAuthorization($url, $method = "GET", array $data = [])
	{
		if (!in_array("sha256WithRSAEncryption", \openssl_get_md_methods(true))) {
			throw new \RuntimeException("当前PHP环境不支持SHA256withRSA");
		}
		$url_parts = parse_url($url);
		$canonical_url = $url_parts["path"] . (!empty($url_parts["query"]) ? "?{$url_parts["query"]}" : "");
		$mch_private_key = $this->WechatPaySdk->merchantPrivateKeyFilePath;
		$merchant_id = $this->WechatPaySdk->merchant_id;
		$timestamp = time();
		$nonce = $this->createNoncestr();
		$this->body = !empty($data) ? json_encode($data) : "";
		$method = strtoupper($method);
		$message = $method . "\n" . $canonical_url . "\n" . $timestamp . "\n" . $nonce . "\n" . $this->body . "\n";
		openssl_sign($message, $raw_sign, openssl_get_privatekey(file_get_contents($mch_private_key)), "sha256WithRSAEncryption");
		$sign = base64_encode($raw_sign);
		$schema = "WECHATPAY2-SHA256-RSA2048";
		$token = sprintf("mchid=\"%s\",serial_no=\"%s\",nonce_str=\"%s\",timestamp=\"%d\",signature=\"%s\"", $merchant_id, $this->WechatPaySdk->mch_serial_no, $nonce, $timestamp, $sign);
		$header = ["Content-Type" => "application/json", "Accept" => "application/json", "User-Agent" => "https://zh.wikipedia.org/wiki/User_agent", "Authorization" => $schema . " " . $token];
		return $header;
	}
}